home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-07 | 10.8 KB | 346 lines | [TEXT/MPS ] |
- {-------------------------------------------------------------------------------
- #
- # Apple Macintosh Developer Technical Support
- #
- # Code to handle events in menus
- #
- # Program: ProcDoggie
- # File: UMenuHandler.inc1.p - Pascal Implementation
- #
- # by: Forrest Tanaka
- #
- # Copyright © 1988-1991 Apple Computer, Inc.
- # All rights reserved.
- #
- -------------------------------------------------------------------------------}
- {[j=20/57/1$] Pasmat Options}
- {$R-}
-
-
- (*******************************************************************************
- * Constants
- *******************************************************************************)
-
- CONST
- rMenuBar = 128; {Resource ID of this application’s MBAR resource}
-
- mFirst = mFile; {Menu ID of the first non-Apple menu in the menu list}
- mLast = mProcess; {Menu ID of the last menu in the menu list}
-
-
- (*******************************************************************************
- * Types
- *******************************************************************************)
-
- TYPE
- MenuGuide = RECORD
- theMenu: MenuHandle; {Handle to this guide’s menu}
- enables: LongInt {Current enable flags}
- END;
-
-
- (*******************************************************************************
- * Variables
- *******************************************************************************)
-
- VAR
- gMenuGuides: ARRAY [mFirst..mLast] OF MenuGuide;
-
-
- {$S %A5Init}
- (*******************************************************************************
- * Public: DoAppleMenu
- *
- * The menu guide array is initialized with the menu handles and enable flags of
- * all menus.
- *
- * If GetNewMBar couldn’t load the MBAR resource, then it returns NIL and the
- * error code is in ResError, and I can deal with the error elegantly. But, if
- * the GetNewMBar couldn’t load the menus themselves, then it’ll probably crash.
- *******************************************************************************)
-
- PROCEDURE StartMenus;
-
- VAR
- menuBar: Handle; {Handle to the menu bar from the MBAR resource}
- menuIndex: Integer; {Index into menu guide records}
-
- BEGIN
- (* Load in the menu bar *)
- menuBar := GetNewMBar (rMenuBar);
- IF menuBar <> NIL THEN
- BEGIN
- (* Set it, then dispose of it because SetMenuBar makes a copy *)
- SetMenuBar (menuBar);
- DisposHandle (menuBar);
-
- (* Add the desk accessories to the Apple menu *)
- AddResMenu (GetMHandle (mApple), 'DRVR');
-
- (* Initialize the menu guide array *)
- FOR menuIndex := mFile TO mProcess DO
- BEGIN
- gMenuGuides [menuIndex].theMenu := GetMHandle (menuIndex);
- gMenuGuides [menuIndex].enables := gMenuGuides [menuIndex].
- theMenu^^.enableFlags
- END;
-
- (* Draw the menu bar *)
- DrawMenuBar
- END
- ELSE
- IF ResError = memFullErr THEN
- gError := memFullErr
- ELSE IF (ResError = noErr) OR (ResError = resNotFound) THEN
- gError := resNotFound
- ELSE
- gError := dsSysErr
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Private: DoAppleMenu - Handle an Apple menu item choice
- *
- * This routine is called whenever it’s determined that the chosen menu item was
- * in the Apple menu. If the chosen menu item that’s passed in the menuItem
- * parameter wasn’t the About item, the name of the menu item is retrieved and
- * then OpenDeskAcc is called with this name so that the desk accessory by that
- * name is opened. The Process Manager can launch desk accessories, but
- * OpenDeskAcc should still be used if the user chooses any item in the Apple
- * menu.
- *******************************************************************************)
-
- PROCEDURE DoAppleMenu (menuItem: Integer);
-
- VAR
- daName: Str255; {Name of the chosen DA}
- refNum: Integer; {Reference number of the DA, ignored}
-
- BEGIN
- IF menuItem = iAbout THEN
- ShowAboutBox
- ELSE
- BEGIN
- GetItem (GetMHandle (mApple), menuItem, (*<*)daName);
- refNum := OpenDeskAcc (daName)
- END
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Private: DoFileMenu - Handle a File menu item choice
- *
- * This routine is called whenever it’s determined that the chosen menu item was
- * in the File menu. The item number of the chosen menu item is passed in the
- * menuItem parameter.
- *******************************************************************************)
-
- PROCEDURE DoFileMenu (menuItem: Integer);
-
- BEGIN
- CASE menuItem OF
- iLaunchFore:
- DoLaunchInFront;
- iLaunchBack:
- DoLaunchInBack;
- iLaunchTo:
- DoLaunchTo;
- iJustLaunch,
- iOpenLaunch,
- iPrintLaunch:
- DoLaunchMode (menuItem);
- iQuit:
- DoQuit
- END
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Private: DoProcessMenu - Handle a Process menu item choice
- *
- * This routine is called whenever it’s determined that the chosen menu item was
- * in the Process menu. The item number of the chosen menu item is passed in the
- * menuItem parameter.
- *******************************************************************************)
-
- PROCEDURE DoProcessMenu (menuItem: Integer);
-
- BEGIN
- CASE menuItem OF
- iBringFront:
- DoBringProcessToFront (FrontWindow);
- iShowProcessInfo:
- DoGetProcessInfo (FrontWindow);
- iTerminateProcess:
- DoTerminateProcess (FrontWindow)
- END
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Public: DoMenuChoice
- *
- * This routine should be self-explanatory.
- *******************************************************************************)
-
- PROCEDURE DoMenuChoice (menuChoice: LongInt);
-
- VAR
- menuNum: Integer; {Menu number of chosen menu}
- menuItem: Integer; {Item number of chosen menu item}
-
- BEGIN
- IF menuChoice <> 0 THEN
- BEGIN
- (* Get the chosen menu item and menu number *)
- menuNum := HiWord (menuChoice);
- menuItem := LoWord (menuChoice);
-
- (* Dispatch the appropriate menu-handling routine *)
- CASE menuNum OF
- mApple:
- DoAppleMenu (menuItem);
- mFile:
- DoFileMenu (menuItem);
- mProcess:
- DoProcessMenu (menuItem);
- END;
- HiliteMenu (0)
- END
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Private: ResetMenuItems - Disable any disableable items and clear marks
- *
- * Disabling all the menu items is done bruteforcedly. It could easily be done
- * by looping through each menu and disabling every item that comes up (disabling
- * the Font menu is done this way), but I thought doing it using the brute-force
- * method was clearer. Then again. . .
- *******************************************************************************)
-
- PROCEDURE ResetMenuItems;
-
- VAR
- aMenu: MenuHandle; {Handle to each menu we’re disabling}
-
- BEGIN
- (* Disable items in the File menu *)
- aMenu := GetMHandle (mFile);
- DisableItem (aMenu, iLaunchFore);
- DisableItem (aMenu, iLaunchBack);
- DisableItem (aMenu, iLaunchTo);
- SetItemMark (aMenu, iJustLaunch, CHR (noMark));
- SetItemMark (aMenu, iOpenLaunch, CHR (noMark));
- SetItemMark (aMenu, iPrintLaunch, CHR (noMark));
-
- (* Disable items in the Process menu *)
- aMenu := GetMHandle (mProcess);
- DisableItem (aMenu, iBringFront);
- DisableItem (aMenu, iShowProcessInfo);
- DisableItem (aMenu, iTerminateProcess);
- END;
-
-
- {$S Main}
- (*******************************************************************************
- * Public: FixMenus
- *
- * FixMenus first disables every available menu item. Then the most basic menu
- * items are enabled. The windowKind field of the front window is then checked.
- * If there is a window open, FixMenus calls a routine that’s responsible for
- * that kind of window to enable any menu items that are relevant to that kind of
- * window.
- *
- * If the front window is a modal dialog, then the basic set of menu items are
- * NOT enabled, and the entire Apple menu is disabled.
- *
- * After this is done, the menu bar might have to be redrawn to reflect the new
- * conditions. So, FixMenus go through every menu to determine if the state of
- * the entire menu has changed. The MenuGuide records are used to help determine
- * this. If the state of any many has changed, then the menu bar is redrawn.
- *******************************************************************************)
-
- PROCEDURE FixMenus;
-
- VAR
- currWindow: WindowPtr; {Pointer to the front-most window}
- currMenu: MenuHandle; {Handle to menu being enabled}
- oldEnables: LongInt; {True if 1+ menu items enabled when FixMenus called}
- newEnables: LongInt; {True if 1+ menu items enabled after menus fixed}
- mustRedraw: Boolean; {TRUE if menu bar has to be redrawn}
- numItems: Integer; {Number of items in a menu}
- menuIndex: Integer; {Index into menu guide array}
-
- BEGIN
- (* Start by disabling all menus *)
- ResetMenuItems;
-
- (* Front-most window determines most menu enabling/disabling *)
- currWindow := FrontWindow;
-
- (* Fix the marks for the launch mode items *)
- currMenu := GetMHandle (mFile);
- CASE GetLaunchMode OF
- kJustLaunch:
- CheckItem (currMenu, iJustLaunch, TRUE);
- kOpenLaunch:
- CheckItem (currMenu, iOpenLaunch, TRUE);
- kPrintLaunch:
- CheckItem (currMenu, iPrintLaunch, TRUE)
- END;
-
- (* Enable any window-specific menu items *)
- IF currWindow <> NIL THEN
- IF IsProcessListWindow (currWindow) THEN
- (* Process list window in front, set up menu items in it *)
- FixProcessListMenus (currWindow)
- ELSE IF IsProcessInfoWindow (currWindow) THEN
- (* Process info window in front, set up menu items in it *)
- FixProcessInfoMenus (currWindow);
-
- (* Assume we don’t have to redraw the menu bar *)
- mustRedraw := FALSE;
-
- (* Check through every menu to see if there are any enabled items in it *)
- FOR menuIndex := mFirst TO mLast DO
- BEGIN
- (* Grab the old and new enable flags excluding the flag for the entire menu *)
- oldEnables := BAnd (gMenuGuides [menuIndex].enables, $FFFFFFFE);
- newEnables := BAnd (gMenuGuides [menuIndex].theMenu^^.enableFlags,
- $FFFFFFFE);
-
- (* Shift left so that we only see flags for existing items *)
- numItems := CountMItems (gMenuGuides [menuIndex].theMenu);
- oldEnables := BitShift (oldEnables, 31 - numItems);
- newEnables := BitShift (newEnables, 31 - numItems);
-
- (* Determine if the menu bar must be redrawn *)
- IF (oldEnables <> 0) AND (newEnables = 0) THEN
- BEGIN
- (* Had some items enabled, now has no items enabled, redraw *)
- DisableItem (gMenuGuides [menuIndex].theMenu, 0);
- mustRedraw := TRUE
- END
- ELSE IF (oldEnables = 0) AND (newEnables <> 0) THEN
- BEGIN
- (* Had no items enabled, now has some items enabled, redraw *)
- EnableItem (gMenuGuides [menuIndex].theMenu, 0);
- mustRedraw := TRUE
- END;
-
- (* Update our copy of the enable flags *)
- gMenuGuides [menuIndex].enables := gMenuGuides [menuIndex].
- theMenu^^.enableFlags
- END;
-
- (* If at least one menu has changed state, must redraw the menu bar *)
- IF mustRedraw THEN
- InvalMenuBar
- END;
-